{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Principal Component Analysis (PCA)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from numpy.linalg import eig\n",
    "from numpy.random import randn, rand, seed\n",
    "from sklearn.datasets import load_iris"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "%config InlineBackend.figure_format = \"retina\"\n",
    "np.set_printoptions(precision=8, suppress=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"color:crimson\">Maximum Variance Formulation</h2>\n",
    "\n",
    "Let $\\mathcal D = \\{{\\bf x}_n | {\\bf x} \\in \\mathbb{R}^D\\}_{n=1}^N$ be a dataset. We seek to **maximize the variance of the projected data**.\n",
    "\n",
    "Consider the following optimization problem \n",
    "\n",
    "$$\n",
    "\\begin{aligned}\n",
    "    \\max_{{\\bf u}_1} &\\ {{\\bf u}_1^T{\\bf S}{\\bf u}_1} \\\\\n",
    "    \\text{s.t.} &\\ {\\bf u}_1^T{\\bf u}_1 = 1\n",
    "\\end{aligned} \n",
    "$$\n",
    "\n",
    "Where\n",
    "$$\n",
    "    {\\bf S} = \\frac{1}{N}\\sum_{n=1}^N\\big({\\bf x}_n - \\bar{\\bf x}\\big)\\big({\\bf x}_n - \\bar{\\bf x}\\big)^T\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 248,
       "width": 386
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "seed(314)\n",
    "nsamples = 20\n",
    "x1 = np.linspace(0, 5, nsamples) + rand(nsamples) * 0.5\n",
    "x2 = 3 * x1 + 5 + randn(nsamples) * 2\n",
    "X = np.c_[x1, x2]\n",
    "X_bar = X.mean(axis=0, keepdims=True)\n",
    "X = X - X_bar\n",
    "plt.scatter(*X.T);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "S = np.einsum(\"ij,ik->jk\", X, X) / nsamples\n",
    "eigvals, eigvects = eig(S)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 265,
       "width": 385
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "l = eigvals.argmax()\n",
    "u1 = eigvects[:, [l]]\n",
    "\n",
    "X_proj = X @ u1\n",
    "\n",
    "plt.scatter(X_proj, np.ones(nsamples), s=10)\n",
    "plt.title(\"Projected Data\", fontsize=15);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sklearn Comparisson"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5.03735819,  5.03735819],\n",
       "       [ 4.84525815,  4.84525815],\n",
       "       [10.25831817, 10.25831817],\n",
       "       [ 6.24658612,  6.24658612],\n",
       "       [ 5.44117203,  5.44117203],\n",
       "       [-1.82480268, -1.82480268],\n",
       "       [ 2.29403076,  2.29403076],\n",
       "       [ 2.17571813,  2.17571813],\n",
       "       [-1.87417678, -1.87417678],\n",
       "       [ 0.01966285,  0.01966285],\n",
       "       [-1.14778433, -1.14778433],\n",
       "       [ 2.1336971 ,  2.1336971 ],\n",
       "       [-0.76726156, -0.76726156],\n",
       "       [-0.81728617, -0.81728617],\n",
       "       [-3.76828303, -3.76828303],\n",
       "       [-1.95309679, -1.95309679],\n",
       "       [-3.84657501, -3.84657501],\n",
       "       [-8.93551976, -8.93551976],\n",
       "       [-5.35347892, -5.35347892],\n",
       "       [-8.16353646, -8.16353646]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "pca = PCA(n_components=1)\n",
    "pca.fit(X)\n",
    "np.c_[X_proj, pca.transform(X)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Proposition\n",
    "\n",
    "The linear projection onto an $M$-dimensional subspace that maximizes the variance of the projected data is defined by the $M$ eigenvectors of the data covariance matrix $S$, corresponding to the $M$ largest eigenvalues"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1 = eigvals.argmax()\n",
    "l2 = eigvals.argmin()\n",
    "\n",
    "u1 = eigvects[:, [l1]]\n",
    "u2 = eigvects[:, [l2]]\n",
    "\n",
    "u1.T @ u2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### An example: The iris dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "iris = load_iris()\n",
    "X, y = iris[\"data\"], iris[\"target\"]\n",
    "nsamples = len(X)\n",
    "\n",
    "S = np.einsum(\"ij,ik->jk\", X, X) / nsamples\n",
    "eigvals, eigvects = eig(S)\n",
    "\n",
    "# Sort in descending order\n",
    "l = (-eigvals).argsort()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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4+ArLaV8zFWUXnQh9S+/TMvcn7wkYq21KNjr9x1aJC4iIiKSCCUKkrjGRmhoSLqaW56eff5zN9+c3M03pxfeIWaWwrkOEEo87rmbhilTqBn3IPWTXoFgEAB///4UHj2KoqNH4e/bF4DCQw4hf/fdqX3scWoffYzmn+YCRmDQQIqOOoqCQw7+bSShVcHee7G0vBy3dGnCcfl69yZ/zz1Wfq6wkMJDDknp9xQRERHpCCUKkrjcXO/RemhYgqy4KO2hpJok/FbfjPxddiF/l10I1tXhliyFvFx8vXphvsgZeb6yMopPOpHik05MrP38fIqOOZrqW29LOKaio0dhubkJlxcRERHJJK1RkISZGXk7bJ90vbwddshANOnjKyjAv3p//JWVUZOEVJWcew45WyS2I1Hu1ltTctaZaetbREREpKOUKEhSio4bnUKdnrnPv6+ggN4PP0Te7rvFLZf/+z2pfGgcVlDQSZGJiIiItE9TjyQp+XvsQc6mm9L06acJlc/beWdyt0r8XIBVja+0lMpxY2ma/j+qx46j4e23cdXV+EpKyNt5J4qOG03u5ptnO0wRERGRCEoUJCnm91P5wH0sPGIEzd99F7dszpAhVNxxe4/f59/MyN1yCyp0MJqIiIh0I5p6JEnz9+tH72eepvCYY6JOl7HSEopOOpHeTz6Or7w8CxGKiIiISEdpREFS4q/oRa/r/k7Z5ZdS998XaJk7F8wIrL02+fsNj9guVERERES6FyUK0iG+0lKKjhqZ7TBEREREJM009UhERERERCIoURARERERkQhKFEREREREJIISBRERERERiaBEQUREREREImjXox6oZf58ah+ZSOOnM3ENDfh7V1Kw//7k7boL5lPuKCIiIiJKFHqUYG0tVX++gtonnoTm5pWu1U58FP/aa1F+9dXk77lHliIUERERka5CHx/3EMGaGhYeOZLaiY9GJAmtWr7/gUUn/IHaJ5/q5OhEREREpKtRotBDVF3+Z5qmT2+/YDDIkvP+RNMXX2Q+KBERERHpspQo9AAtv/yS3ChBczPV992fuYBEREREpMtTotAD1DwyEVpakqpT9+RTBJcvz1BEIiIiItLVKVHoAZo++STpOq6ujuZvvslANCIiIiLSHShR6AFcQ0On1hMRERGR7k+JQg/gq6xMrV5FRZojEREREZHuQolCD1AwfHjSdQLrr09gvfUyEI2IiIiIdAdKFHqA/L1+j69fv6TqFB13LGaWoYhEREREpKtTotADWCBA+ZirEi6fM2QIhSNGZDAiEREREenqlCj0EAUH7E/5P68DX/w/ec4mm1D54Fh8BQWdFJmIiIiIdEVKFHqQoqNH0ef5Zyk49FDIyVnpWmDwYMrGXEXvp5/E37dvliIUERERka4ikO0ApHPlbrYZFbfcTMtfxtD8zde4+gb8lZUENt5IaxJERERE5DdKFHoof0Uv/Ntsk+0wRERERKSL0tQjERERERGJoERBREREREQiKFEQEREREZEIShRERERERCSCEgUREREREYmgREFERERERCIoURARERERkQhKFEREREREJIISBRERERERiaBEQUREREREIihREBERERGRCEoUREREREQkghIFERERERGJoERBREREREQiKFEQEREREZEIShRERERERCSCEgUREREREYmgREFERERERCIoURARERERkQhKFEREREREJIISBRERERERiaBEQUREREREIihREBERERGRCEoUREREREQkghIFERERERGJoERBREREREQiKFGIwcwON7NbzOwtM1tmZs7MHsp2XCIiIiIinSGQ7QC6sD8DmwHVwFxgw+yGIyIiIiLSeTSiENt5wPpAKXBalmMREREREelUGlGIwTn3Ruv3ZpbNUEREREREOp1GFEREREREJIJGFDLMzKbGuKQ1DyIiIiLSZWlEQUREREREImhEIcOcc0OjPR8aadiyk8MREREREUmIRhRERERERCSCEgUREREREYmgREFERERERCIoURARERERkQhazByDmR0MHBz6sV/o6/Zm9kDo+4XOuQs6PTARERERkU6gRCG2zYHj2jw3OPQA+B5QoiAiIiIiqyRNPYrBOTfGOWdxHgOzHaOIiIiISKYoURARERERkQhKFEREREREJIISBRERERERiaBEQUREREREIihREBERERGRCEoUREREREQkghIFERERERGJoERBREREREQiKFEQEREREZEIShRERERERCSCEgUREREREYmgREFERERERCIoURARERERkQhKFEREREREJIISBRERERERiaBEQUREREREIihREBERERGRCEoUREREREQkghIFERERERGJoERBREREREQiKFEQEREREZEInZYomFnAzFYzs5wEyq5vZsM6Iy4REREREYmU8UTBzHqb2UPAMuBnYLmZPWVmm8apdinwRqZjExERERGR6DKaKJhZETAFOArIBwzIBQ4CPjKzMzLZv4iIiIiIpCbTIwp/AjYE/gfsABQBmwL3AjnAv83sbxmOQUREREREkpTpROEwvClHw51z7zvn6pxznznnTgYOAKqAi83sDjOzDMciIiIiIiIJynSisC7wrnPu17YXnHMv4I0y/AicDEwws0CG4xERERERkQRkOlFowRtRiMo59wWwI/AFcATwjJnlZzgmERERERFpR6YThTnAkHgFnHM/ATsBHwP7AC8BpRmOS0RERERE4sh0ovAxsJGZrR+vkHNuCbA7MBkYBhyc4bhERERERCSOTCcKz+FtiXpeewWdczXAvsDToToiIiIiIpIlmV48/DLeQuWmRAo75xrN7HDgTKBXJgMTEREREZHYMpooOOfq8M5MSKZOEPh3ZiISEREREZFEZHrqkYiIiIiIdENKFEREREREJEJaph6Z2XcdbMI559ZJRywiIiIiItJx6VqjMBBwpL5bkUtTHCIiIiIikgbpXsycyg2/tkIVWRU5B3WLoaURCiogkJftiERERCQJmd4eVUR6muXzYNo9MPVOWDbXe84XgA0Phq1Ph4G7gunzARERka4unYlCov/nbx110J2CyKrmqxfg8RHQWL3y88Fm+Pxx7zFkJBx0P+TkZydGERERSUi6EoUT2rmeC6wJbArsD/jxEoZZwP+lKQYRyabZb8AjB0OwnfMVZz7iJQ6HTwSfNl4TERHpqtKSKDjnxiZa1swGA48CWwIbAX2cc9enIw4RyZJgEJ49qf0kodXnj8OXz8JGB2c2LhEREUlZp3+c55z7DjgCCOJNP7rGzNbv7DhEJI2+fRmWJLlL8ke3ZyYWERERSYusjPs752YDX4Z+zAXOzEYcIpImnzyYfJ3vXoHlv6Q/FhEREUmLbE4QLmXF2Qt7ZzEOEemo1t2NkrX85/TGISIiImmTle1RzezPwABW7IC0RjbiEJE08aX4n5JU660KFn4JMx7ykizzQ+8NYbPRUNw325GJiIgAaUoUzOy+BIrlACXAJsBgVj6cLcEVkCLSJfXZCOa8kVwdfx6UD8xIOF3agi/ghTNh9muR1167zNs+dt+boaBX58cmIiISJl0f5x1P4qcyt56f0DrtyAFfpCkOEcmGLU9OfnHykBGQX5aZeLqqX6bD2D2gfkn068EmmPEg/DIVjn8Tinp3bnwiIiJh0j3un8ghatESiolpjkNEOlP/zWGtneGHtxKvs00P28OgfhmM3y92khBuwefewXXHRRl1WDIHPh0PVT94U5Yq14ffHaOkQkRE0i7diUKiowrhPgZuS3McItLZDn0Q7tkeqhPYyWjPf8CArTMfU1cy48HEXptWs1+Hnz5a8TotmQ0vngNfPU/Ef2pfvQQ2PQr2vlFTlkREJG3SueuRJfkIAuOAvZxzjWmMQ0SyoXxtOPEd6LdF7DI5hTD8Vtjp4s6Lq6v46D+p11kwC+7ZDr56jqifx7Q0wP8egPt2gpoFHYlSRETkN+kaUUj0ZOZGYCnwOTDJOadN1EVWJb0GwR+nwpw3YeqdMO8TaK6H4n7eIt3NRkNBebaj7HwNy2HBZ8nXm/seNNbC+OFQM7/98gs+h0ePgOPfAEtkJqiIiEhsaUkUnHMnpKMdEVkFmMGgXb2HeJpqU6838xFYOifxOt+/CXPfhzW3T61PERGRkGweuCYi0jPklZHYXg9tFFTAx6lMWUpyByoREZEolCiIiGRaTj6sm8IB9OvtBz9/nHy9H99Nvo6IiEgbShRERDrD1qcnV9783k5GqWisSa2eiIhIGCUKIiKdYb3hMGj3xMvvcD5UbuAlDMnSFqkiIpIGShRERDqDzw9HPgFr7th+2S1Pgj3+Dv6Al2Aka4MDk68jIiLShhIFEZHOUlAOo1/1DkarWDfy+po7wGET4IC7wBf6z3OyU5YwGPrHDocqIiKS7pOZRUQknpx82P482PYc+OkDWDYXfAGoXB/6bhJZfp29YNAeMPu1xNrf+jSoGJzemEVEpEdSoiAiHbd8Hiz+GoItUDoAKtfLdkRdn8+X2FkHPh+MeALG7wc/vhO/7JCRsM/N6YlPRER6PCUKIpK62W/AB/+GL58FF1zx/IBtvCkzmx7tzbOXjskv86YsfXird0bC0tkrX++3OWx7Nmx23IopSyIiIh2k/4OLSPKcgzeuginXRL/+04feY9o9MOJJKOrTufGtinLyYccLYPs/wQ9vw7IfvR2RKteD/lt6J2JLz7RkNnw7CeqXQm4xDNw1+jQ2EZEkKVEQkeS9e33sJCHcD2/D9f29XXy2PUs3L+ng88HAYdmOIjOa6qH6F290qrgf5BZlO6Kube6H8OZf4OsXAbfytbWHwc6Xw7p7ZSU0EVk1aIw6DjNbw8zuM7OfzazBzOaY2U1mpk3KpeeqXQSvX5F4edcCU++E/2wGU+/OXFzSff36KTx3KvyzN9w8GP69LvyjFzx+FHz/draj65pmPQX37wxfv0BEkgDw/RR4aB/48PZOD01EVh1KFGIws3WAqcAJwIfAv4DvgHOA98ysMovhiWTP9PuhpSH5eq4FnjsFPp2Q/pik+3r3xlASeSc0hZ0oHWyCmY94N8MvnO0tlBfPTx/D4yOhpbGdgg5eOAO+fK5TwhKRVY8ShdhuB/oCZzvnDnbOXeKc2x0vYdgAuDar0Ylky+ePd6z+C2d5U0yk6wi2wLeveiM+H9/lfd8ZN+Yf3gaTzifqJ+IrlbsFJl2Y+Xi6i7euTSBJCPPGVd66IhGRJGmNQhRmNhjYC5gD3Nbm8lXAKcCxZna+c64GkZ6kdkHHrnRy+wAAIABJREFU6tctgs8fg82OTU88krrmBnj/JvjoP1D1/crXytaCrU7zznwI5KW/79pFMOmCxMu//y/Y/Djot1n6Y+lOqn70dhlLxrzpMPcDWHO7zMQkIqssJQrR7R76Osm58D0fwTm33MzewUsktgPinoJkZlNjXNqww1GKZEMgv+NtfDpBiUK2NVTDhANgzuTo16t+gNcuhW9eglHPQ15xevuffh80Jzmy9NHtcMCd6Y2ju5n9+spbESfq20nZTRQWfQPT7ob5M73RkOJ+MOQoWHcfbekr0oUpUYhug9DXr2Jc/xovUVifdhIFkVVO/6Gw4POOtVE9Lz2xdCX1Vd4uT/VV3haVa/w/e/cdXcd1Hfr/Oxe4F70DBAgQvRAAe+9VpEhKpCiqy7Lc5CrLTpz8nOS38l4cJ37PL/XFdmwntmzFsWVLlq1CFfZOSuxgBUB0kCBBEJ1EB+6d98cIEAHcMjO4F4Xcn7WwLOHOOXMIwdLsOWfvvRhCJ431qpxTVXjzOddBwt2qD8Efn4Vnt3u3BOvF35obs/k/xrYUbGcLlO+CjgYtaE5cAAkzvTe/wwEVe+H0f0DtGS2YCo6D/Cdg3pe03y8zum97b41GtDfA9i/ClXeGf3bhNxCVAQ//VKozCTFOSaDgXMTH/+vq38j934/0NJGqqvOcff/jnYa5xpcmxBib/1W48OuRzeGLoyxjpbEMPvwnuPDq4GRcixWmPQlLvw2TZ4/d+pypOWHs+ErJe1BzXF8nab3u1Bof09OmfQWEeW8derVchcPfg4uvQm/H4M+Sl8Kyv4DcrSO7R3MlvLYN6s4P/n77LTh0Wbt/zsPm5h6Ln1l7PfxyBTRecX1NcwW8+hA8+XvIf2z01iaE0EX2+8zpf50l2WHi/pO8BKaM8IFx0gzvrGWsVR+Bn82HMz8bHCSAVrXn4m/h5cVQ+ObYrM+VUyZKZpoZ447F5Hsqi9W769Cj9hz8fIF2dGZokABw7UN47VE48Lfm79FyFX65fHiQcDfVbjw/oV/6Ws/XeNtbn3EfJPRT7doOV3Ol52uFEKNKAgXn+ncMIlx8Hj7kOiHuH4oCT70BkWnm55j/Fa8tZ8w0XIHfboZuD/8asHdrpSzHUz+Ash3Gx1x4Ff7OBt/1h39KgPdfgluXnV/bXAlFb8Ol16HyINh7h19jpvleVIbWoXo03amFVzdpb/U9OfRdrWqUGdtfgDs3zI31ZNIMSFnum7ldqbuk5bfo1dfl/WBUCDFiEig41/8KJMfF59kf/6+rHAYh7m3hSfDCR5D9kPGxKSsg0emJvInl0N/rP/ft6IX9f+3b9RjR1WJikKr9OVQ7tNfBqR/DT6ZrjdL6A4HyPfCbTVrTtNe3aQHSr9bA/03VSnR2Nn8y3TwTwaKZMSN14kfGcmoOfgf6DJQuBagv0vISDDGQp7Hqb0Y/r+OMiaTzgl9qlbiEEOOG5Cg4d+Dj/31QURTL3ZWPFEUJA5YBncDxsVicEONCWAI89z40lsKuP9POsXsSkQKPm0hiHW/a67USr0ZUH9bessZP982ajLCFmgwWnDjzn9BzB2Jy4eDfOL+mrRYO/Z22w/D8LohMhamPaLtSLVX61zzn8yNfb3MlnP5PKHpT2yWwBkHifC33JmsjWPw+ubavG86+bGz+tptQ/BZMf1r/mLO/MHaPARbAQwWk9f8I054wOf8I1BYYH9PZpJV/jcny/nqEEKbIjoITqqqWA7uBNODrQz7+LhAC/Lf0UBACiMmGT70Lz7wNoZNdX5e2Gl74ECKmjNrSfKZ8t7GGV/1KxkmH3NSV3p3v4m9dBwl3a7yi7Th03wE/f3j6LQgI9zzO4g9PvAYhcebX6HDA7r+AH2TCsX+AplLt2FjbTS3I/e1mrUN0U8UnY26cMdc3pNTg0a6mUuP3QIVN/wapq5x/PHkuPP0mLBujRnVmureD8ZK5Qgifkh0F114EPgR+qCjKA0ARsAhYg3bkaBydIxBiHMjdqh1FKn5HqwzTdlNLPJ00HeZ9efxV/hmJzqbRHdfP3qs9NI/0GMn8r5lPih2phiLtiMniP9F+Jz5/BP7wNDQUO78+NAGyHoLz/60ljYdMgvwnIWOd/vr7qgoffF0rOepO/WUtofiLH2m7Hp7yT1xpvWbsej35D85MmgGLvqHlipTt0naJbKFaUJ60YGzLyAabDOpGEgwKIbxOAgUXVFUtVxRlPvB3wEbgIaAW+CHwXVVVR/hffCHuQX5W7ZjDWBx1GE3WYHPjFD/tzbaRBlM3L2j5AJffgK5mUCyQMFs7KjPjU2ALMb6OzAe1+v83Thkf6w2nfgqLvqk9yCbMhBcvQ+U+7ZhPUxk47FoeTG+nVlnq3C8Hjz/7MkRnwaYfQvYmz/crec9zkNCvrRa2fwk+s1t76Dajaj/8ah1s/YUWcHhiplQsQESy9r+TpplLDvelaU8ZT5pPXQWh8b5ZjxDCFDl65IaqqtdUVf28qqqTVVW1qaqaqqrqn0iQIMR9zmx52GP/AN8LhNcfh4p92ptuV+x98N6L8B+ztDfpXR8nAqsOqD0L734ZfpgFNSeNr8NigWffgehsz9f6QuMVrWrU3evJXA9Pvg5fOQMvHNN2X6oOgNrnfI6mMu240MXfeb7fiR8ZW1/FHqgv1gIys8FC5T6tNG5TufvrWq9Ba7Xx+aMyIDrT3NpGw/SnISja2JgFX/PNWoQQpkmgIIQQRk3Kd3023BNHr5ZI+9/rPi6v2jb8GlXVAoHTP3U/V9tN+O8HtDr/RoVNhtmfNT7OW9wdw3r/61qDN09UB7z1WbjlplN4S7X24G9UwS+1JmWzPmN8bL+2m/C7rdoOiSt1F8zNHZ5sbtxosQbBhn/Vf336A5D3uO/WI4QwRQIFIYQwY/lfjnyO0g/gta3Dy2mWvAfnXtE3R08bvP0597sTzvR1w4kfGhvjTa6Ob92+ARd+o38eRy+cdLNj4OmNvstxZdr/Lv4WWE0c7+pX/3H+gCtmkuLBfeGA8WL2Z2HjD/BYyjVtjZZ47SenoYUYbyRQEEIIM7I3wYP/PPJ5KvdrR4vudvLHxuaoO691BzaivzzoWAiMgtipzj87+7LWq8GI87/WKik5ZTCAGhj2cdnRmCx4+o/gH2RuHnC/MxQyydycvkr6NRpwerL4m/ClEzDzefCzDf4scQFs/aVWMjdQR/UrIcSok/BdCCHMWvrnEJYEB/7nJ2+gzTj1Y1j4dS25904tlLt5A+3Kuf+ClGX6r6/cb/we3jLn89rRFGfMJFj3tmtVk5IWDP8sIsX4fDA4CTlrA3z+EOz5Sy1vwqgbZ1x/NmWxtsbWq8bmPPOfWlWmBV+HKQuNr6mfqmrHvE79BEre/7hyUojWGHHBi1pAfHdvCTOSFsBj/w2bfqD9/8Teo1WzGs85FkIIQHYUhBBiZGY8Ay9dgU/vhMV/CvGzjM/RUAzXP35AbjGR2GpmnN6u0t5mDdYebl0xW0e/t9P592OyIXmp8flmDcnfSFoAn9LRVNAZd38mi5+5jtP2Hq1k7MuLtADGzE5ATzu8/hj8Yql23KurGVC142xlO+B3W+BnC6C1xvjczgRFaT/HlGUSJAgxQUigIIQQI2WxaG+dN/5fmDzH3Bz9b5QVk/9aNlIz3+GAzmZz9xkRBZ58A6IzXF8SHGtuandHcdwFJs5MWQKJc4d/3xpkLl/B0zGhhS9B3AjKmx77R9j/P4yN6euB3z0CxW+7v+5mAfzXaq0buRDiviOBghBCeJPZB/3+4x2RaebmiNL5hranA1571FwloBFTIc1DtSgzlW/i8iE21/Xn05+BfJ29PQIi4JGfO/9MUSDfxPo8/ZkCw7Vz+vEzjc/d78j/htrz+q8/8UP9x8+ay2HXn5tblxBiQpNAQQjhXfZe7e1jT/tYr2RsmO1N0D8udBLkbDE+fu4Lnq9xOLQuyCXvGp/fWzx1p87dCmGJxuZc8KL7HRWLBR77Dcz8tPt5whLhs/vdNy9b8KKxtaHAfB1Hi8KT4IWP4KEfm99d+OVSuKojqd3h0HISjLj8uuwqCHEfkkBBCDFyDgeU74HXtsH3guCfJsH/DoUfT4MT/w5drWO9wtEz63k8loMcKmkRxE//5O8XvmR8fOI8z9cVv6WVXh1Lnrpa+1nhwX/RP1/CbJj9ec/X+QfAtv+GLx7X8g8GjhApMHkebPk5fKPE+ZGjuyUt9Bxw3G3Zt/V1ZwawBcPCF+HFi1rnaaN6O7S+Gtc+cn9d9WFoqTQ2t70HLv7W+JqEEBOaVD0SQoxMdxv84RkofX/4Z/WFsOMbcPh78Oz2kVVnmShK3sNwSc6hgUHmOlj0J3DiB57HBkXDtl/pu4/Rt8jeFp2tr1vvjGe0xNoPXvqkTKkz8bPguQ+0B2w9FAWmLNK+Hn1F6yXhZ9N2HPRSFHjkZS1BufAP7q+d/zV44Pv65777Hh0NxseBtq4/PAPfLHfdl6C5wtzczQaDi6FUFWoLoK0WLFbtyFjElJHNKYTwKQkUhBDm2Xvh9W1Qsdf9de118Ov18IWjED9jdNY2Fhx27ay4EREpMPO54d/f8K9amcoj38dl4BGVoQVgrnoS3K2tbmxLogLM/6r+pOsFX9Pe9J/4AVx+Q2us1i86W5tr/le0n5EZigLWQHNj/QPgidfh8u+10rZXjw7+PGujFvxlP2QsyfxulhH857n1qhaw5j3q/HOzazKrt1PrFXLqJ9BYctc6LJD9MCz+E8h4YHTXJITQRQIFIYR5Ba94DhL6dd+G974GLxz1fO1EVfqB8Xr4rTVa74TwIefyLRZ44H/B3C9pD6PnfqWd71cUsIVB6kpY932Iy9N3n7abxtblbcFxMPtzxsZMWQhTXtW6+9YXam/LQ+K0nQQjuwC+YLFoOx8zntG6P7de1R58ozIgInnk88fla0eEzDr7sutAITLd3JxRbqpVudLRCK8+BNdPDv9MdWj5MiXvwurvwuq/MbcuIYTPSKAghDBHVbUHWCOuHYOb5yHBRK+BiaDqkIlBDq2r8jQXVXmuHtWaqfUfRVHRjuVceUf7yn1U624bFOX+NharibWhPfyGJcLtIbX0g+NgxqegdAc0lTgf288Wpu18BOs4duRMSCyErDQ31lu672hHjZrKtN/9yFSY9pT2c4/O9H5fgHlfHlmg0Fzu+rPUldpDv5EjSH4B2j9vI/p64LdbnAcJQx38jvazXPQNY/cQQviUBApCCHPqLkLdBePjzv/63g0UetpMjrvj/Psn/l3L8XCn+G3tjfbnD0NQpOvrItPAFmp8japDCxJipsKSPwd/m9ZVN221dgRn9Xfgg29oVXEcfcPHp6yAh388cY+cdd/RehQUvDL8n9POb2kPz+v+jxbMeFP+E7DnL+DODXPj3eV2WCxab4ndBkqeTn/G+J/x8u+hxkNi9d32/bWWmB4Qauw+QgifkapHQghzbl8b3XETQWCEyXFOHvCvn4Id39Q3/tZFeO+r7q+xBcPM542vrV/jFTj/K22OrA1akADaW+DHfwPfuqYl7s76jPbwvPTb8NXz8IXDEzdI6GiCV1ZqPQecBXN9nVDwC/jFErh9feT36+2ExlKoL9b++um3zDV4A4jwUGlp4UuQsU7fXNFZ8OA/G1+D0eT5njtw8VXj9xFC+IwECkIIcxQ/c+NGkqQ53mVtMj7GPxBSnTQhO/4DDFVPKnwDWjzkRyx8yfw/N9COjpXvcv5ZWAKs+CutAtPjr8KD/wgJI2ggNtZUFd54Em6e83xtUxn8djPYneyo6FF3Ed79CvxjHPwoB36cB/8YA0e/D+v/QTu6ZZSnfBB/GzzzDuQ95v66yfPgc4eM7ya01RnbTehX9KbxMUIIn5FAQQhhTkzO6I6bCNJWQazO5OJ+058dfna/o0l78DdCdWgJrO5Myoct/2ls3qFOGsxLGU+un4J3XoCfzIAfZMHPF8PRf3DeSOzqMWNVom6eM9ej4vgP4KeztKpAvXc1KVQd2rGyD15yHki6EzJJXwdpWzA89Qett0TWJu1ommLRel1kbdJKz37p5PBEez3MNmfraDQ3TgjhExIoCCHMic6A9LXGxigWfc2xJipF0SoV6RUQDsv/cvj3G4q1BldG6ckZmfsCPPEaBJs8U1+xR3vbPpG01cF/rYGfL4SCX8KtS1qy7/UTsPev4F+nwKHvDf5zmek5YXTMmZ/Dzj/F485R6XsQP1vfnIqf1liu/2iYOw6HtoZ3vgBlO7T8FdWhNW67fkILlLpa9N13KE+N9VyOCzI3TgjhExIoCCHMW6TzDH2/3EchMsU3axkv8rbBph/hsTuzLQyeedt5DwQzQQKAvVvfddOfhj+rAX8TD2X2Hq1R2UTR3qDlGVQddH2NvQcO/E/Y/e1PvldtooJV1UH9QVRXq5YMrVfdOc9Bti1U+53K2uB5Pocd3voMvPcVrfTsUJ1N8OE/a/kXrSbyiiKStZ0NoxIXGB8jhPAZCRSEEOZNfUSrnqJHVCY8/FPfrme8WPQSPL8b0p00kfKzwYzn4EsnIH3N4M/6eqC5SusXYEZogv5r/QP0dUkeyuKv7231ePH+i4ObfLnz0b9AyQfaX3e7qETljqNXf5B37leDjxrpYe+Bl67A4m8N3hGKydGSjf+0CqZu1jfXnr/QlzjcWKL1Qeg1+DvpZ9V6gBg1/yvGxwghfOYezioUQvicosCmH2rVfo7+A6h259dNWQJP/xFCTbxhnKgy12lfDVe0Pgk97VqFoIz1w38ODSXasZVz/wXdrebvOf0ZY9enr4ULvzY+xhedfbtaoblSK7EangRhk0c+Z+s1KPqjsTEnfgg5D2m/067K1rriF6AFgnpces3Y3KDlrTz6Cmz8V+2rrwcsftqXEXdqtT+nXrcuaeud8zlj95n/Va2ztt6SvFO36usyLoQYNRIoCCFGpr+D8IKva8m0RW9CZ6N2rCVpASx4EZKX+ubhciKIner+4efsL+HdL7sOsvSKytSCECMWvGg8UFjworHrXXE4oKFIayh3ZTtU7Bt8dCr9Ae1euY+a78Jc8Ir7fgLOlO+C90z+GbM26P89b6s1Pr+9BzqbPwk0/XUGJUOdfdl5zwt3Tv3YeKAQMUVLlv7dVs/H4uJnwaP/ZWx+IYTPSaAghPCO8ERY/Tfal9Dn4u9g+wsjn0fx05qaGX2gnrIIMh+E8t36rp88F7IfNr6+u3W3aQ+qp3/q/khQ5T7tK+8xeOxVsAYav1dDkbk1njZ5RE7vMTww3ynbz+S4u5XuMD7mxmmtIlFwjLFxWRvgs/vhg687LzVr8dcqfz30I/N9SIQQPiOBghBCjIWeDnjfwIOlK34B8Niv9SWwDqUo8MTr8Ov12oOgOzE58Oy74DeC/2y01sBvNkL9Zf1jit7Ukm6ffN34rpRjhLs0RsRN09/ADGDSdGgqNXaPsCTnzfmMMlvJqKvFeKAAkLIUvnIWao5rwXFbrXZEa9J0LUE7zEBujRBiVEmgIIQQY+Hy69DVbH58QITWVGvh1yEm2/w8QZHwuYNw8G/h7C+Gr8kaonVbXvv35h4S+3Xdht9scF5hx5PCN6Diy1rOhyu9nXDpda3MZ1eLVgFoNGvy11/WujTP05nAO+/LUPyWsXvM+7J3jvDZQkd3HGjrTl6ifQkhJgwJFIQQYixc/K2JQRb4wmEIjIKodO/VnLeFwIP/BKu/qzX5airVynxGpkLe4xAY7nmOhhLtSFF9oXb+PSwRZj73SfLzqZ+YCxL6nf6p80BBVbWmZYf+bmSBlze891VtZyFlqedrMx+EuHz9PxP/IP1BiCdpq+DGKWNjYqaaK3cqhJjQJFAQQoixcOeGiUEO7fhJVJp311JbADUnoK8TgmK0JOKQOH1j79Rq3Y7LnJx7P/eK9oC5+adwZoQdoYvf0XYNhgZHe/8Kjv3jyOb2FtWh9R5IedPztRYLPPVH+OVyLfnfHcUPHv+tdypBgVaN6MN/NjZmwYv3b0ECIe5jEigIIcRYGMtk1n6Ff9Qesq+fHHIPG0x7Clb9jftjTbdvwC+XQUuV62sar8CvN2g9BkZCtWtHiSKmfPK9y38YP0FCvyvvaLkYd6/TlbhceOEY/OFZuFng/JqwJNj6C3M5KK5EZ2q9PPT0UQAInwKzP+u9+wshJgwJFIQQYixMmgZ1542NCYqGkHjv3P/Ad7TjOs7Ye+DCb6Dkffj0Dq060lCqCm885T5I6DfSIKHf0EZvRt+KjwbVoSWG6wkUQCud+5UzcPUYnP251nfD0ac9nM/6DEzd4t3gsN+Wn8HtGs8dqIPj4LkPpCKREPcpCRSEEGIszPuy8TyFOS+MrOpQvzMvuw4S7tbVDK8+rFWsiUwZ/Nn1k3Dt2MjXoldYonYsql/tObh+wvg8IZOg/dbHf6N8/Pd1XlnigN4OY9crCqQu175Giy0Ynt+lJbGf+Rl0Ng1Zkx/kbYN1/wDRGe7nunkBKvZC920ICIeMByBhls+WLoQYPRIoCCHEWEhdCQmzndeWd8Zi1c6Wj5S9Fw4Y6HXR2QjH/03rBHy30yPMOTBq3lcG94moPWtunjlfgKX/n5bvEBSl7Zr84WnvrLHfhd9oR5BsoZCyAqY/7b3Ec2/yD4B139eOmBX+8eNE9F4tKJv2lNYh253yPXDwu84DxuSlsOo7kPWgb9YuhBgVEigIIcRYUBR48g34xVLoqPd0MTz6iuc3u3oUv2O8K/C5V2Dt97S30P3MPqibYQ0ZXvGnr8vcXH3dg8u85j4KoQnQdtP8+oa6O7G74Jew68+04GT5X5nvMu1L1iCY9WljY878HN79CqA6//zah1rPjM3/AfO/POIlCiHGxjj8N5YQQtwnYrLghQ+1jseuBMfB03/USo16Q/ku42O6WoYnPNu7vbMeTyz+8MRrwyv+mC3VObSak78NNv3Q3Fx6dTXD/r+G7V/UcjsmuvK9WilYV0HCAFW7rnzPaKxKCOEDsqMghBBjKSYLvnxaS2Y98zNoKNKSicOSYOanIf/x4Um8I9HVam5c95BxwXFAscFJFDw/XN4lMh0eeRky1g7/LGuDdrSnp83YEvKfGP69aU9C18+1h1rVh92cz70C8TNhyZ/67h6j4fDfa0nbuqhw6O8hc71PlySE8A0JFIQQYqyNZjKr6a68YYP/ftqTcPWIsTmyH4IZn4I933bRR0KB0Hgtf2P25yBzg+ujOgFhWlWgUz/Rf/+M9a7Lvc77IiQthJM/gguvaj0l+kWmQ2u1gYdjNz76F1j4kneS0sdC3SWoPmxszNUjUHcR4mf4Zk1CCJ+ZoP+mEkIIYUr6Gu3NthHWEEicP/h7sz6jNTszUuFnwdcg52EtyLiyHYrehI4Gretw0kIt0TgsQf98K/5a6yStp3mdNQTWe+i5kDATHvk5PPgv0FSmHa8KiddyQ66fgg//BYr+qJUvNet2DZS8B3mPmp9jLFXuNzeuYp8ECkJMQBIoCCHE/ST/Sdj5Lc/dgO8263kIDB/8vcAIWPd/YMc39c2RsxmyNml/7WfVjlTlP65/Dc6EJ8Lze7Sk2dvXXF8XEAHPvAWTZ+ubNzAcEofkjSQtgCdfg7Y6rU9CTzvcODWsl0OfYqXBP5leSxBWRyexvdfwZ0gfiesnJ26g0HPH3Lju295dhxBiVEigIIQQ9xNroFZ9Z8+3dV4fAou/5fyzRd/QHgD3/w/3c2Rt1BKSfVHxZ1I+fLUATv+H9nW75pPPgqK1XYqFL0FkqnfuFxqv7YrAoGDrjl80l0Ie4ErwEnosIQPfD3C0MbXjQ6a37SPU0aJ902ifhfEkINzzNc5IwzYhJiQJFIQQ4n6z9M+huVx7sHbHP0iruBSb4/qalX8NaavhxI+GH8uZsgQWvAjTn/HtmfzgGG0dy/4S6i9rVZpsoRA3TQuMfOXjBnC1tix2RX+dHkvwsEu6LaFcCH2QK0FL2dj078T3VkJwrO/W5GsZ60yOk2RmISYiCRSEEOJ+oyjw8E8gfhZ8+E/QXDH8mswN8MD/gsR5nudLWaZ9tTdoAYj946Zd3uj7YISf/+h2BM58kKaAdHZGvUSvxX1DtW6/UHbEfJNH679PZO4EPXYEEJenBYZVBwd924HCtYDpFIWspNGajB1/ghx3SO86Q15UHyGT8sdkuUKIkZFAQQgh7keKAgu+CvO+DOW7tXPzvR3a2+7cra6rA7kTEqt93S+CIjmd+BV6u/V1Xe6xBHM64YssDErB0taG1Wqlurqa4uJiWlpaUFWV0NBQsrOzycnJITDQh7shI7HqO1B9ZKCUbIvfJHZHv0iLdXCviy6/MJqtiRT0wdwzZ5g7dy6KoozFioUQJkmgIIQQ9zOLBbI3al8TVXsDtN/S+k2EJ2tN1EZBW1sb1d1RWhM1PQ/AqkoFqVS89prLS7q7u2lsbOTUqVMsX76cqVOnenHFXpK+Grb+At55gduWKLbHfpsuP9e5Cypw5swZ+vr6WLRo0agtUwgxchIoCCGEmHgcdih6S+ujUHXgk+8HxWgJzAu+BlHpPl1CVVWV1j5O71tyA2/T7XY7hw4dwuFwkJeXZ2p9PjX7sxCRysG9x+hS9SU4nz9/nuTkZBITE32ypJaWFmpra+nt7cVms5GUlERYWJjngUIIlyRQEEIIMbF034HfP6EdmRqqs1HLuzj5I3jsVch/zGfL6Orq8tnc/Y4ePUpSUhLh4SarDflQQ9h0bqolhsZcunTJ64HCjRs3KCgo4Pr164O+rygKKSkpzJkzh0mTJnn1nkLcL3xQq04IIYTwEXsvvP6Y8yDhbn1d8MZTUObhuhHw9/f9uzZVVSkqKvL5fcwoLi42PKa6uprOzk7PFxpYw/vvvz8sSADtZ1ddXc327dupqqry2j2FuJ9IoCCEEGLiuPg7qNir71rVDu99FRwOnywlLi7OJ/MOdeXKFVRVHZV7GXH7tvEmaqqqcueOyaZtQ1y7do0jR454/NnmyGLRAAAgAElEQVQ4HA727t1LfX29V+4rxP1EAgUhhBATx6mfGLu+pRLKdvpkKYmJiURE+L6RWFdXFz09PT6/j1FmgxdvBT2nT5/WPZfD4eDs2bNeua8Q9xPJURBCCDExNFfC9RPGx138LeQ85PXlKIrCzJkzOXLkiNfnHqr/gdhut1NVVUVlZSWdnZ34+/sTGxtLXl4eoaGhPl/H3czezxvrrK+vN7xDcPXqVdra2kb95yTERCaBghBCiInhTq25cW03vbuOu+Tm5tLQ0ODTPAKr1YrNZqOsrIyPPvpo2Bn/a9euce7cOTIyMlixYgU22+iUh83JyeHKlSuGxiQlJRESEjLie9fU1Bgeo6oqNTU15Obmjvj+Qtwv5OiREEKIicHPOrrjdFAUheXLl7Nw4UICAgJ8do+DBw+yf/9+l4nAqqpSXl7O+++/T29vr0/WMVRCQgLR0dGGxkybNs0r9zZ7FGs8HuESYjyTQEEIIcTEEJ0NfiYexidN9/5a7qIoCrNnz+a5555j1apVZMUHk9pzmehe42+9nenp6aGsrEzXtfX19Rw7dswr9/VEURRWrVqlu/pTVlYWqampXrm31Wou+But3RYh7hUSKAghhJgYgiJh2lPGx837svfX4oS/vz9T/apZe/7zbGj4IRsbf4SfOvpvsEtLS+no6BiVe8XFxfHQQw8RGBjo9rqcnBxWr16NYqDpnDtmezFMnjzZK/cX4n4hgYIQQoiJY9E3AQMPmzmbISbbZ8sZpLcL3vw0OPoACHW0sKb5FRTVN+VZXVFV1VSPA7MSEhJ45plnWLp0KVFRUQPf9/f3Jycnh0cffZTVq1djsXjvkSM+Pt7wsacpU6aMSpUqIe4lkswshBBi4kiaDxv/DXb+iedro7PgkV/4fk39Ct+AjsGVeDK6zmJp+imHI5+ny2/0uis3NjaOyn36E4TLy8vp7OwkIiKCtLQ0srKyiIyM9NoOwlCKojB37lz27tXXU0NRFObMmTPs+z09PfT29mKz2UwfZxLiXiaBghBCiIll8TchIBx2fQu6Wpxfk7EOHvsNhE4avXUVvOL022ndF0iu+/+pDJpDadBi2vyisGAn0N7O9cA8nyzFbrf7ZN67Xbt2jWPHjg1rvFZVVTUqVZgyMjJYuHAhJ0+edHudoiisXLly4NhRX18fZWVlFBYW0tDQMHBdfHw8+fn5ZGRk4Ofn55M1i3ufqqrcunWLGzduDAShycnJxMTEjPXSTJFAQQghxMQz53NavsLl1+Hy76H9FvgHQsJsmPcVSJg5+mtqrnD5kR99ZHWeIrnrEk3WKfQpVlr84n0WKAQFBflk3n4VFRXs27fPZcOz/ipMLS0tbN682WcVoWbPnk14eDgFBQVOd1Hi4+OZN28eU6ZMAaC1tZUdO3Y47SpdV1dHXV0dFy5cYOPGjV4p4yruL5WVlZw9e3bY7+LJkyeJj49n/vz5JCUljdHqzJFAQQghxMRkC4Y5n9e+xgM3x2ya/CdzMWQdZUELsVt8X3knMzPTZ3O3trayf/9+XV2RGxsbOXz4MOvXrzd0D1VV6enpwc/PDz8/P7dHmDIyMkhPT6euro7a2tqBt7hTpkwhNjZ24Lr29nbee+892tvbPa75/fff55FHHvGYpC1Ev/Pnz3PihOuGkHV1dXzwwQesWrWKnJycUVzZyEigIIQQQnhDZDq0VA37dkXgXPZHvYBDGZ3/5EZERPj0reWlS5dwOPQnaFdWVnL79m3Cwz3naNy6dYvCwkLKy8sHjk+Fh4eTl5fH1KlTXT64K4pCQkICCQkJLuc+efKkxyChX0tLCwUFBSxZskTX9eL+VllZ6TZI6KeqKocOHSIsLGzCVOCSqkdCCCGEN8z5wrBv1dhy2Rf1xVELEhRFYenSpT5LIu7r66OkpMTwOE+dqx0OB4cPH+btt9+mpKRkUI7F7du3OXHiBK+99pqpjswAnZ2dlJeXGxpTUlJCX1+fqfuJ+4eqqpw5c8bQ9QUFBT5ckXdJoCCEEEJ4Q/4TEPJJ8rQKHI94ElUZncRYi8XC2rVrSU5O9tk9bt++barz891Jw0Opqsrhw4c9lnTt6elh586d1NbWGr5/RUWFoV0QgO7ubq5evWr4XuL+UldXR1NTk6ExNTU1tLa2+mhF3iVHj4QQQghvsAbCY6/Cq5vA0UedLZMm6xSvTZ+bm0tsbCyFhYWDHkysVivZ2dlMnz6dyMhIr93PGbNv2O12O6qqUldXN5BIHBYWRkJCAteuXdO9S+FwODh06BBPP/20oV0TvUeOvDXO05xXrlyhoaEBu91OUFAQGRkZTJkyxau9JsTouHHjhqlxtbW1E6KvhwQKQgghhDd0tkD9ZQhLgtZqKgLnemXayMhIZs6cydSpU1EUhby8PG7fvk1XVxd+fn5ERESMWg8As9WUenp6+P3vfz/sLWp4eLjhUqS3b9+mpqbG0M6J2Qdwbx7h6unp4ejRo5SXlw9LBC8pKSEsLIxly5aRkpLitXsK3+vpMdd93czO3FiQQEEIIYQYqdId8IdnoPuTsptdljBTU+Xm5hIaGoqfnx9xcXFMnjx50AOroihERESMydvIsLAw4uLiqK+v93zxXVwdzXBWplSPkpISQ4GC2Z0Wb+3Q9PT08N5777k9gnXnzh127drFmjVryMrK8sp9he+Z7RPiq/4i3iaBghBCjLKenh4qKipobW1FVVVCQ0PJzMz0ee174SNlu+F3j4Bj8LEcf9Xcm8bU1FRSU1O9sTKfyM/P59ChQ2O6hra2NkPXp6WlERAQQHd3t+4xYWFhXqsedeTIEbdBQj9VVTl48CAxMTFERUV55d7Ct5KTkzl9+rShMYqiTJh+ChIoOKEoihV4EZgNzAHyASvwJVVVXx7LtQkhJq6enh5OnjzptJrK8ePHyczMZNGiRQQHB4/RCoVhfd3w1vPDggSAuN5qillhaDpFUcZ9B9esrCyKi4upq6sbszUYPUrk7+9PXl4e586d0z1m2rRpXjl61NbWRkWF62Z8QzkcDi5dusSKFcZ+d8TYiIuLM7zLlpKSQmhoqA9X5T2SNeNcCPBvwOeABODmmK5GCDHhdXV18e6771JYWOg0IdThcFBaWsrbb7/NnTt3xmCF95aenh4KCwvZv38/u3bt4uDBg6Yq33hU+AetK7QTmZ0nsTo6DU0XGRnJxYsXOX78OEVFRabPP/uSn58fGzZsYNKkSZ4v9hE9PRmGmjt3ru7a9ampqUyfPt3wPZwpLi7W1ZzubqWlpRPmDLuAefPm6b7WYrEwZ84cH67Gu2RHwbkO4CHgnKqqtYqi/C3wnbFdkhBiolJVlX379tHY2Ojx2ra2Nnbu3Mljjz1mOMlTaAHX6dOnuXz58rAHrZKSEoKDg1mwYAFTp071zg3P/ZfLj2xqN/nthzkftgFU1W3n5n7Nzc00NzcP/P1HH31ETk4OCxcuHFdnmgMDA9m8eTMlJSVcvnx50JpHQ25ursdrHA4H1dXVFBUVUV9fT19fHwEBAURERLgtTZmbm8uyZctobGzk5s2b9Pb2EhAQQHJysqkAxWg+B2jVpVpbWwd1lhbjV0pKCitWrODo0aNug0KLxcIDDzwwpkG2URIoOKGqag+wY6zXIYS4N9y6dYvr16/rvr65uZmqqioyMzN9uKp7j8PhYN++fVRWVrq8pqOjg0OHDtHZ2cns2bNHftNm1/cCWHDnbZqsiVwLnGFq+r6+PgoLC7l16xYPP/wwAQEBpubxBX9/f/Lz88nLy6OlpYXOzk66u7vZs2ePT+8bFxfn8UGrpaWFXbt2DQsIOjo6Bv46OjoaVVXp6+vDZrMxZcoU8vLyaGpqYvv27U4f8JOTk5k3b56hB727m8cZIc3eJpa8vDzCw8MpKChwWjI1JSWFuXPnTqggASRQ8DlFUVy16/P8OkQIcU8oLCw0NUYCBWPOnTvnNki428mTJ4mJiRl5czIPuwQWHDzY9FNOhj9GYfBK7BZzuwINDQ3s27ePhx56yNR4X1IUhaioKKKiokw1QzMiICCANWvWuM0duH37Ntu3b6erq8vtXE1NTeTk5LBq1aqB+c6fP8+JEydcjrl27RrXr19n3bp1pKWl6VpzYGCgruuGMlLcoKuriytXrlBbWzsQ+KSkpJCVlYW/vzzqjZakpCSSkpJobm6mtraW3t7egSA0LMxcFbSxJr89QgjhY2Yenmpra3E4HNKASSe73c6lS5cMjblw4cLIA4WoDGgqc3uJH3aW3H6DuXfepyR4CXWBOfRlP0JPTw83b+pPgaupqaG+vp64uLiRrdmHjJ7FNyIiIoINGzZ4LFl6+PBhj0FCv5KSElJTU0lPT6e8vNxtkNCvf+dq69atuo4GZWRkGEpmBm23Q88xJ4fDMZDPMnTnoqqqiuPHjzN37lxmzJjh1Z4Qwr3+wPleIP8F8jFVVec5+wLc96oXQtwzzCYlmj2ycD+qrKzU/XDY7/r1627Pqusy5wu6Lw1QO5jRvo91WTY2btxoKrHazO7UaPJWJRer1UpQUBChoaGkpKSwceNGnnzySY9BQnNzs+FOuZcvX0ZVVc6ccXUAYDi73a67glJaWprhSmb5+fkeH+wdDgd79uzh0qVLLv9d0dPTw/Hjxzl58qSh+wvR757dUVAUpQowUoj6VVVVP+2j5Qgh7mM2m81Q/XbQjnPIkQH9bt1yXnnIk/r6+pE1LsvdBqGToU3vrpEC87+K3W43tWZfHO3p6emhrKyMW7duDST8pqamkpycbPgtdHh4OEFBQXR2Gqv2NFR0dDRbt241PO7KlSuGx9y4cYOysjJaWloMjausrKSjo8NpENDe3k5bWxuKohAWFsaSJUvYt2+frnnj4uLIycnxeF1BQQHV1dW65jx//jxxcXFkZGToul6Ifvfyf4XKASOvl4y9ghBCCJ2Sk5MNvwk285B2PzO7+zLiXRt/GzzxO/j1g2DXUcr0wX+GuFz6DAaO/bxZMtNdhaiioiLCwsJYvHgx6enphuadMWPGiN9gmw2SzXZ6vnr1quExqqpSW1s7kEukqirV1dUUFhZSU1MzcJ2iKKSkpDB9+vSB3QtX4uLi2Lhxo8c/v91u5/Lly4bWe/HiRQkUhGH3bKCgquoDY70GIYQA7RiB0UAhPz/fR6u5N5lNGNU7rr/PRV1dHXa7nfDwcGbMmKGVLE1bBc/tgDeegk4XJXAtVtjwL7DoG4B2tEZRFMNn+r1V9cjhcLB3716qqqpcXnPnzh327NnD8uXLDf0+zpo1i0uXLg2qMGRUQkKCy8/a2tpobW3F4XAQEhJCVFTUiINqsxWG+vtcOBwODh06RGlp6bBr+gMI0JrVKYpCRUXFoCA1KiqKvLw8cnNzdQVJZo7a1dXV0djYOO4b+onx5Z4NFIQQYryIjo4mKyuLsjL3Sa/9Jk+ePPIk2/tMeno6BQUFhsb4+fkRHx/v9hqHw8HRo0cpLS0dtvtw5swZ4uPjeeCBBwjNWAvfqoaLv4MzP4OGYq1bc/gUmPU8zP0ShH3y8GuxWEhKShr05lkPb/1enDlzxm2QcLdjx44RHR3t9uH9boqi8Pjjj/PGG28YfpjtH++sT0JNTQ0XL17k2rVrg74fHR1Nfn4+U6dONZ0jYbYbutVqBRj4HfGkrKyMOXPm8Nxzz9HS0oLdbicoKMhwsNPQ0GBqvRIoCKMkUBBCiFGwcuVKuru7hz3kDBUXF8f69evl2JFBsbGxxMfHU1dXp3uM3W7n9ddfZ8GCBU7fmDscDn7/+9+7Pc5SV1fHa6+9xtatW7VqRPO+qH3pkJ+fbzhQ8MZOU29vr6FjK6qqcuHCBd2BAmilPZ999lmOHDlCeXm5oZ2TnJwcQkJCBt3/1KlTLpOHm5qaOHr0KBUVFcyfP99w9auEhAQyMjIoKioyNE5RFBITE2loaKC4WH99knPnzpGXl2fo5zmU2Q7jviyQ0NraOtCgzmazkZSUNOifo5iYJFBwQVGUv+KTXgf9XXk+ryjK8o//+qiqqi+P/sqEEBORv78/GzZs4NKlS1y+fJk7d+4M+jwoKIi8vDxmzZo18JZSGLNo0SLee+89Qw9R3d3dHD16lK6uLubOnTvos+3bt+s68+5wONi+fTvPP/+8oe7JKSkphoKbqVOnjizx+mPl5eUDR2b0qq6upr293dCDn9VqZe3ataxcuZIzZ85w/vx5j2MSExNZtmzZoO+dP39eV4WhGzducPbsWcMB47Rp00hMTPTYsXmo9PR0goODOX36tO4xoAU+RUVFLFiwwNC4u41Gbwa9bty4wblz54YFvYqikJaWxty5c2UXYwKTQMG1jcCqId9b+vFXPwkUhBC6WSwWZs6cyYwZM7hx48bAQ0loaChTpkyRngkjlJCQwLp169i3b5/hN6enT58mLi5u4GhPY2OjoapEdrud48ePs3LlSt1jLBYLGzZs4IMPPvB4lCQ1NZXly5e7vUYvM9WWVFWloaHB1Btif39/Fi1aRGZmJh999JHTyk1Wq5W8vDwWLFiAn5/fwPe7uroMlS2tqalh+fLltLS06Ko0lpiYiKIoXLt2jenTp3Ps2DFd91EUhb6+Pg4cOEB5ebnu9fWrqKgYUaCQkZFhOEDpf8vvTUVFRRw9etTpjpGqqlRWVnL16lXWr19PSkqKV+8tRocECi6oqrp6rNcghLg3KYoy0MFTeFdaWhqPP/4458+fN1wq8+LFiwOBwvHjxw3fu6yszFCgANqb4S1btnD+/HmKi4uHJQBHREQwbdo08vPzvRZImj1+4irht/8h0dNxudjYWLZs2UJTUxMVFRV0dHTg5+dHTEwMmZmZTnfSSkpKDK+3urqaLVu2sHPnTtra2lxe5+/vz40bNwb6LvR3mG5ubvZ4D1VVTVVK6jfS8rGRkZEkJSVx/fp13WNycnK8ult59epVjhw54vE6u93O3r172bp1q+wsTEASKAghhLinREZGEhcXZzhQqKmp4fbt24SHh5t6697X10dLS4vHpmBDWa1W5s+fz9y5c6mpqaG9vR1FUYiIiCAhIcHr+SpmKyfdfdylp6eH0tJSiouLaWlpGahAlJWVRX5+vtuk4ujoaKKjo3Xds7Ky0vA6r127xrp163jqqaeoqKigqKiI+vp6HA7HwNGwnp6eYYGPqqoDQUJISAjt7e2G763X3bsmZi1atIjt27frqtgUEhLC7NmzPV6nV3/eiF59fX0UFBSwbt06r61BjA4JFIQQQtxzzFaFaWpqIjw83PRb9/b2dsOBQj+LxTIqxzPS09MNJ/wGBgYOJN/W1NSwd+/eYXkObW1tnDt3jvPnz7Nw4UJmzpw54iDHTNWk/nFhYWHk5OSQk5ODqqp0d3ezfft2XY3V2tvbmTdvHlarld7eXsrKykbexfsu3nizHhsby8aNG9m9e7fbnJOwsDA2bdpkurKTM/X19TQ2uigF7IK7BnVi/JJAQQghxD1npFVhLBaLqTnMJpmOpoSEBN1HbPrl5ubi5+fH9evX2blzp9ufjaqqnDhxAofDwZw5c0a0VrNv3of2IlAUhZKSEkPdl4uKivjUpz5FQ0ODoTwJPVxVr7pz5w6NjY04HI6B4MzdkbPExESeeOIJLl++THFx8aC8jLCwMPLy8sjLy/Na/41+nqq3OaOqKtevXyc7O9uraxnPVFXlxo0bFBUV0dzcjMPhIDg4mMzMTLKzsydE4QoJFIQQQtxzzJ7n768KExkZaXhXwmKxEBUVNfD3DoeD9vZ27HY7AQEBPqk4Y4aiKCxevJidO3fqKlsaEhLCjBkzsNvtHDhwQHcAderUKVJTU3UfM3ImLi6OpqYmQ2NCQ0OHBWyqqhpuetjR0UFVVdWIchGciYiIGLZzdP36dS5cuDDsATw4OJi8vDymT5/u8mE/NDSURYsWMX/+fJqbm+nr68NmsxEZGemzAglGq2aNdNxE1NLSwt69e4f9/ra2tlJbW8uJEydYtmwZOTk5Y7RCfSRQEEIIcU+5efOm7uZ2dwsODh44XrNgwQJ27NhhaHxycjIWi4WOjg4KCwuHJSfHx8czbdo0MjIyxrzCVXJyMqtXr+bgwYNug4XQ0FA2bdpEUFAQ5eXlhrstFxYWjqhaU35+vuFck/z8/GFHnpqbm3WVuh2qqqrK9DE2ZwICAnjwwQcH/fMvKChwed6/o6ODM2fOUFZWxsMPP+w298PPz4/Y2FivrdUds2/CJ8IbdG9obW1l+/btbo/O9fb2cvDgQex2O3l5eaO4OmOkFp8QQoh7xu3bt9m5c6euBM+hcnNzBx7gkpOTDZcCXbJkCdevX+f111/n7Nmzwx6q6+rq2L9/P++++67ps/felJ2dzbZt28jKyhoWuAQFBTFnzhy2bds2sEti9IEdoLS01PQxMNB2FBITE3VfHxAQwNSpU4d9fyS5DmZ+l5yJj4/n0UcfHbTrVFxcrCspuLW1lQ8++GDcvJGfPHmyqXF3N5nr6OigsbGRlpYWr/2MxwNVVdm7d6/u37mjR48aOhI32mRHQQghxD3j/Pnzph6mIiIimDFjxqDvbdu2jddff53e3l6P49euXUtXVxc7d+70mAhdV1fHzp072bx587Cz9HqpqkptbS2tra2oqmq6F0dsbCxr165l6dKlNDQ00NfXR0BAAJMmTRqWHzC0SaAevb29dHV1jSiBde3atbz77rsek4n9/f1Zv3690yNeZn/O/v7+BAQEuC2z6kpCQgJdXV309PRgtVpxOBxcunSJvLw8oqOj6evr4+TJk7rna2lp4cqVK8N+T8eCmQZ1ycnJhIaGUlFRQWFh4UBZWtB2GnJycpg2bZrpYgDjxc2bNw0lequqyuXLl4c1GhwvJFAQQghxT+gv2WlUaGgoDz/88LAz4MHBwTz77LO8//77Lv/DHxQUxOrVq5kyZQpvvfWW7mpJt27doqioyPBDX//DprPu3v3n2WfNmmX4wTgwMJApU6YYGjNagoOD2bp1K0eOHKGqqsrpUanY2FhWrFhBXFyc0zkiIyPx9/c3/OZ60qRJxMTEGK7wExkZSWNj47Ags76+nsuXL5OcnExqaqrhnY7CwkKmT5/u9ZK5RimKwty5czlw4IDu62fMmMGuXbucJkL39vZy+fJlCgsLWbVq1bg/t+9OcXGx4TElJSUsWrTIdEDrS+NvRUIIIYQJN2/eNHWEISUlxeXZ78DAQB5//HE6Ojo4ceLEoMolc+bMGTiCcevWLcNn2Y0+9PX19bFnzx6XFWf6z7NfvXqVhx56yOuVbsLCwgyXCLVarV6pBBUYGMj69etpa2sb1rshOzubuLg4tz9Hm81GdnY2RUVFuu9psViYOnUqqqpy9uxZXYnf/TwdJbl27Ro3b97UPV+/1tZWWlpaBh1fGivZ2dm0trZy9uxZt9cpisKKFSu4ePGix2pJqqpy8OBBrFYr6enp3lzuqDFzjKi3t5eOjg7Cw8N9sKKRkUBBCCHEPeHu0pBG6AkugoODWbNmjcvPzSRPt7a20tDQ4PIt+FCHDx/WVZayvr6e3bt3s3nzZq++eZ46dSo1NTWGxmRnZ3s1cTs0NJT58+ebGjt9+nSuXLmiO2di6tSpA8eYZs2axblz50zd1xU9R9qcMft77gvz588nMjKSs2fPOn1AnjRpEvPnz6enp8dQSdWjR4+SkpLilcZ0o81sTs5Icnl8SQIFIYQQ94SxrMRitBqQ0XFNTU2GgpHa2lpqampITk42tS5n0tLSCA4ONvRnDQ8PZ/fu3bS3tw+Uj83NzWXSpEleW5deUVFRrF27ln379nncHUhMTGTJkiUDf79gwQK6u7s97kgEBAT4/EHe6PGUlpYWSkpKuH37NqqqDjSiG0nZ2rtlZWWRmZlJbW0ttbW19Pb2YrPZSE5OHgiC3333XUNzdnZ2UlVVRWZmplfWOJpCQkIMH1VTFGXcNqKTQEEIIcQ9YdKkSSiKYuiICJiv4HI3s2/N9Y4z2gMAGDgL7y1+fn6sXbuWDz74QNfbT6vVyvHjxwd9r66ujuLiYuLj41m7di1hYWFeW58eGRkZBAQE8OGHHzptOOfv709ubi6LFi0a9DZbURSWL19OUlISly5dGnZsKCIigqysLK83Zhuqvz+CHm1tbRw+fNjpLtCFCxeYPHkyK1as8ErysKIoJCYmOq1Q1dHRQW1treE5y8vLJ2SgkJWVZbj3RmpqKjabzUcrGhkJFIQQQtwTgoODSU9Pp6KiwtCYtLS0Ed/b7NtZvWfNzXTCrampQVVVrx4/SkxMZNOmTezdu9fjm3N3R2vq6up455132Lp166gHC0lJSTzxxBPcvHmTiooKurq6BnoQZGdnu8ztUBSFjIwMMjIyaGlpoaWlBVVVCQkJIS4ublAVH1/JycnRtaNw+/Zttm/f7nb3p7a2lnfeeYctW7Z4bXfBmc7OTlPjzO7SjbX09HSCgoIM/blddeoeDyRQEEIIcc+YPXs2VVVVus/7zp492ytn6HNycjh16pSh3Yz+cpF6mCn56nA46Ovr83qTq6SkJJ599lnKysqGJRanpKRQVFSk6+ff0dHBnj172LZt24iDGYfDwdWrVykrK6OjowNFUYiKiiI/P9/pQ7CiKEyePNn0blJkZOSwN/G+PmPu7+/P9OnTPV7ncDjYtWuXrgft7u5udu7cyVNPPeWzijtm//81EfMTQFv3ihUr2LNnj65/H+Tk5JCUlDQKKzNHAgUhhBD3jNjYWNasWcP+/fs9/kd62rRpTJs2zSv3DQ4OJisry1B5ViOlUf39/Q2ffVcUxWcPfzabjfz8/GFvQk+cOGHogbmhoYHKykoyMjJMr+Xq1ascOXKE9vb2Qd+vra2lsLCQxMRE1qxZY7iBnlFmz5jryfuwWCw88MADuqriXL161emxKlfa2tqoqKjwWUnSsLAwrFar4eRtX+5y+FpaWhoPPPAABw4ccFsyOScnh5UrV455uVt3pDOzEEKIe0pmZjzfQMEAABlASURBVCYPP/ww8fHxTj8PDQ1l+fLlLF261Kv/gV62bJnuh5s5c+YY6ltg5s13QkLCqD6AOBwOU92bDx48aPqYSUVFBbt27RoWJNztxo0bvP3226aaphkRHR1tqmzpmjVrmD59usugLjY2ls2bN5OamqprPiMlYEcyRi9/f3+ys7MNj8vLy/PBakZPRkYGTz/9NLNnzx7UBLD/CNvmzZtZtWqVV6uC+YLsKAghhLjnJCYmsnXrVhoaGqiurqa7uxt/f38SEhJMdTDWw2azsWXLFg4cOOAymdHf35/58+cbbrSWn59vuATraJ977ujoMNxADLTytKdOnWLVqlWGxt25c4cDBw7oOt7R3t7Ovn372Lp1q+H16aUoCvn5+Rw7dkz3mJiYGBITE0lKSmL+/PmUlpbS2NiI3W4nKCiIjIwMjz0ihqqvrze89vr6eq/ns9xt2rRpFBUV6T6al5SUNKF3FPqFhoaycOFC5s+fT1dXFw6Hg8DAwHHZWM2VibNSIYQQwqDY2FhiY2NH7X4BAQFs3LiR5uZmioqKuHXrFna7nYCAANLT08nOzjZV3SQ+Pp7ExETdCbNRUVGj3rBqJGf0y8rKWLx4saEmcYWFhbo7YYOWQH3r1i2flmbNzc2lrKyMuro6j9daLBaWLVs28HBus9m8chTOTNNBh8PBjh07mDFjhlcrZfWLiopi5cqVHDp0yOO1YWFhbnuWTEQWi2Xclj/1RAIFIYQQwsuioqJYunSp1+ZTFIV169bx/vvve6zRHhoaysaNG0f9SENgYKCp8rQAdrudyspKcnNzdV1v9phTUVGRTwMFPz8/Nm7cyO7du92WBLVaraxfv56EhASvryEwMNDUMauamhpqamqYOXMmixYt8vruwtSpU7FarRw7dsxlRaCkpCTWrFkzYR+q70USKAghhBATQGBgIFu2bOHkyZOUlJQMe3NssVjIyMhg8eLFY/KgZbPZSElJobq62tR4Zw+3drudqqoqmpqaBiorZWRk4HA4TB1zampqMrU2IwICAnj44YeprKyksLBwUMAQFBREXl4eeXl5PkuuTktL49KlS6bHX7hwAZvNxty5c724Kk1GRgapqalUVlZSXl5OR0cH/v7+REVFkZeXR0xMjNfvKUZGAgUhhBBigrDZbCxfvpyFCxdSXl4+0G03NDSUzMzMQUmTYyE/P990oHD3DojdbqegoIDCwsJhAcFHH31kKBH8bkaOKo2ExWIhMzOTzMxMurq6Bno1hISE+HynJz8/f0SBAsDZs2fJy8vzye+Tn58fWVlZZGVleX1u4X0SKAghhBATjM1mG5dVYaZMmUJCQsKwzsV6REREANoZ+927dzvtKAygqqqpBnTAmARSgYGBBAYGjtr9IiMjmTZtGpcvXzY9h8PhoLi4mDlz5nhxZWIiGt81mYQQQggxYSiKwsaNGw03ywoMDBzokH3s2DGXQcJIZWZm+mTe8WbJkiUj7otQVVXlncWICU0CBSGEEEJ4jZnz7Xl5efj5+XHnzh1KSkp8tq775biLxWJh1apVrFu3znTytquEY3F/kaNHQgghhPCqWbNmUVtbq2tnYPLkyQOBhZFa+0YtXbp0oH59Q0MDhYWFXL9+nd7eXqxWK0lJSUybNu2eSajtb+yVlJTEr371K8PjJ1Ktf+E78lsghBBCCK+yWCw8+OCDHDlyhNLSUpfXpaens3r16oGjSu5Kio7E0qVLycnJoaenh4MHDw47VtPV1UVxcTHFxcUDa7JarT5Zy2iz2WxERETQ2tpqaFxcXJyPViQmEgkUhBBCCOF1/v7+rFmzhjlz5lBYWEhNTc3A2/vExETy8/OHdd/t7e01da8lS5ZQXV09qCGdn58f2dnZA7sEfX197Nixw2MztMrKSrq6unjooYcM51qMR4qikJeXx/Hjxw2NG+3O3mJ8kkBBCCGEED4TGRmpu/mcma7VoCUpz5gxg46ODjo6OrBYLISGhg6ar6CgQFfHZNB2Ns6dO8e8efNMrWe8ycnJoaCggO7ubl3Xx8fH+7QxnZg4JJlZCCGEEOOCmf4IMTExA2VPg4ODiY2NJTo6elCQYLfbKSoqMjRvYWEhDofD8HrGo8DAQDZs2KAr7yAsLIz169d7vTOzmJgkUBBCCCHEuJCbm2u4IVl+fr7Hh9rq6mrDnZw7Ozu5evWqoTHjWUJCAo888ojb3IO0tDS2bt06Jp29xfgkR4+EEEIIMS4EBwczffp0Lly4oOv6yMhIsrOzPV5nNJF3pOPGq9jYWLZt28atW7coLS2lvb0di8VCREQEubm5hIWFjfUSPWpvb+f69ev09PRgtVqZPHky4eHhY72se5YECkIIIYQYNxYuXEhHRwdlZWVurwsPD2fTpk26jtOYLbnqq1KtY23SpEkTLgehoaGBs2fPUl1dPeyfS3JyMnPmzCEhIWGMVnfvkkBBCCGEEOOGxWJhzZo1JCQkcOnSJVpaWgZ9brPZyMnJYe7cuQQGBuqaMzQ01NRazI4T3lVdXc3evXux2+1OP7927Ro1NTWsWrVqxB2pxWASKAghhBBiXFEUhfz8fPLy8rh58ybNzc04HA6Cg4NJTk423OMgLS0Nq9VqqPyqzWYjNTXV6NKFlzU0NLgNEvqpqsqhQ4cICQkhKSlplFZ375NAQQghhBDjkqIoTJ48mcmTJ49oHpvNRnZ2NoWFhbrH5OTk3DNN1yays2fPegwS+qmqyunTpyVQ8CKpeiSEEEKIe978+fOJiIjQdW1kZOQ900NhImtra6O6utrQmLq6OhoaGny0ovuPBApCCCGEuOcFBgayefNmYmJi3F4XGxvL5s2bCQgIGKWVCVdqampMJZTX1NT4YDX3Jzl6JIQQQoj7QkhICNu2baOqqorCwkJu3LgBaEecEhMTyc/PJzU11XAvB+EbPT09psbp7UAtPJNAQQghhBD3DYvFQkZGBhkZGTgcDvr6+vD395fgYBwymyMiuSXeI4GCEEIIIe5LFosFm8021ssQLphNYk9MTPTySu5fEj4LIYQQQohxJzIy0nAFo4CAAF1N+IQ+EigIIYQQQohxafbs2SiKovv67u5u3nzzTS5evOjDVd0/JFAQQgghhBDjUlJSEsuXLzc87qOPPjLUN0M4J4GCEEIIIYQYt/Ly8ti4cSORkZGGxh0/flwqII2QBApCCCGEEGJcS0lJITY21tCYvr4+SktLfbSi+4MECkIIIYQQYlxzOBxUVFQYHldWVuaD1dw/JFAQQgghhBDjWnd3Nw6Hw/C4jo4OH6zm/iGBghBCCCGEGNfMNsSTRnojIz89IYQQQggxrtlsNkJCQgyPi46O9sFq7h8SKAghhBBCiHFNURTy8vIMjzMzRnxCAgUhhBBCCDHu5ebmGuq6HBkZyZQpU3y4onufBApCCCGEEGLcCw4OZu3atbo6NQcEBLB+/XpDXZ3FcBIoCCGEEEKICSEtLY2NGze6zVeIiYlh69atREVFjeLK7k3692+EEEIIIYQYY8nJyTz77LNUV1dTWlpKe3s7iqIQERFBXl4e8fHxspPgJRIoCCGEEEKICcVisZCenk56evpYL+WeJkePhBBCCCGEEMNIoCCEEEIIIYQYRgIFIYQQQgghxDASKAghhBBCCCGGkUBBCCGEEEIIMYwECkIIIYQQQohhJFAQQgghhBBCDCOBghBCCCGEEGIYCRScUBQlW1GUv1QUZb+iKNcURelRFKVOUZR3FEVZM9brE0IIIYQQwtekM7Nzfw88DRQCHwBNwFTgEeAR5f+1d/9BdpX1HcffX3aXZPmZSmQyMJZNsCwxCYFSY4Xyo1KpJdaABcc64IBTrZ1Oi2MpZaaA2namYmuLttNqB2os4PDL0bE2CdoCgpUfFUFGE1ogiZgQwJhEICRZYr7945wly567y26ye87uve/XzJ0z9znnbr7Jk3vvfs55nudEXJqZn22wPkmSJGlSGRRaWwVck5kPD22MiDOAbwJ/ExG3ZeamRqqTJEmSJplDj1rIzOXDQ0LZ/i3gbuBA4JS665IkSZLq4hWF8Xu53O5utApJkiSNaM+ePWzdupWBgQF6enqYNWsW3d3+6jse/muNQ0QcA5wFvATcM8bXPDTCruMnqi5JkiQVdu7cyZo1a1i9ejXbt29/pX3GjBn09/ezcOFCDjnkkAYrnD4MCmMUETOAm4AZwOWZubXhkiRJkjTE1q1bWblyJS+++GJl365du3j00Ud57LHHOPvssznqqKMaqHB6ads5ChGxPiJyHI8bR/lZXcANwKnALcDfjrWOzDy51QN4bL//kpIkSQJg+/btrFixomVIGGpgYIBVq1axefPmmiqbvtr5isKTwM5xHP90q8YyJNwIXADcClyYmbn/5UmSJGmiPPzww68aajSa3bt388ADD7B06dJJrmp6a9ugkJln7e/PiIhu4EsUIeFLwPsz8+f7+3MlSZI0cQYGBnj88cfH9ZqNGzeybds2Zs2aNUlVTX9tO/Rof0XEgcDtFCHh34CLDAmSJElTz4YNG3j55Zdf+8Bh1q1bNwnVtA+DQgvlxOWvAMuA64FLMnNPs1VJkiSplZ07xzPafK8dO3ZMcCXtpW2HHu2nzwHnAJuBjcDVETH8mLsz8+6a65IkSdIwXV1d+/Q676swOv91WptbbmcDV49y3N2TX4okSZJGc8QRR9T6uk5hUGghM89sugZJkiSNzezZsznyyCN57rnnxvya3t5e+vr6Jq+oNuAcBUmSJE17J5xwwriOX7BgwT4PWeoUBgVJkiRNe/PmzWPx4sVjOravr48TTzxxkiua/hx6JEmSpLawZMkSDjroIB566CEGBgYq+7u6uliwYAFLlizhgAM8X/5aDAqSJElqCxHBokWLmD9/Pk8++SRPPfUUAwMD9PT0MGfOHI477jhmzpzZdJnThkFBkiRJbaW7u5v+/n76+/ubLmVa85qLJEmSpAqDgiRJkqQKg4IkSZKkCoOCJEmSpAqDgiRJkqQKg4IkSZKkCoOCJEmSpAqDgiRJkqQKg4IkSZKkCoOCJEmSpAqDgiRJkqQKg4IkSZKkisjMpmvoSBHx097e3tfNnz+/6VIkSZLUxtasWcOOHTu2ZOYR43mdQaEhEbEOOAxY33Apg44vt481WoUG2R9Ti/0xddgXU4v9MbXYH1PLVOqPPuD5zJw7nhcZFARARDwEkJknN12L7I+pxv6YOuyLqcX+mFrsj6mlHfrDOQqSJEmSKgwKkiRJkioMCpIkSZIqDAqSJEmSKgwKkiRJkipc9UiSJElShVcUJEmSJFUYFCRJkiRVGBQkSZIkVRgUJEmSJFUYFCRJkiRVGBQkSZIkVRgUJEmSJFUYFDpYRKyPiBzh8UzT9XWqiDgtIr4cEZsiYle5/UZEnNN0bZ0iIi4e5b0x+Ph503V2kohYWr4PNkTEjohYGxG3RcRbm66t00ThAxFxf0S8EBEvRcTDEfHHEdHVdH3tKCLOj4h/iIh7I+L58jPoxtd4zSkRsSIitpR99GhEfMQ+2n/j6Y+I6ImISyPiCxHxSEQMlMf/Xt1174vupgtQ434GXNui/cW6CxFExJXAXwKbga8Dm4DZwEnAmcCKxorrLI8Anxhh32nA24CV9ZXT2SLiGuBy4KfAVyneH28ElgG/ExHvz8xRf2nShPoicBHwHHALsB34DeAzwOkRcUF6N9eJdiWwmOK7eQNw/GgHR8Qy4MvAToo+2gL8NvD3wKnABZNZbAcYT38czN7fs54FngHeMKnVTSDvzNzBImI9QGb2NVuJACLiAuBW4D+Bd2fmC8P292Tmy40Up1dExH3ArwLLMvNrTdfT7iJiDrAR+AlwQmY+N2TfrwN3Ausyc15DJXaUiDgX+AqwDliSmZvL9h6Kz69zgUsyc3ljRbah8v/6BuAJ4AzgLuCmzLywxbGHlccdDpyamd8t22dSvF/eCvxuZt5cU/ltZ5z9cSBwFvBIZm6KiI8DHwM+mJnX1Vf1vnHokTQFRMQBwDXAS8D7hocEAENC8yJiIUVI2Aj8R8PldIpjKL6rHhgaEgAy8y7gBeD1TRTWod5dbj89GBLglc+nq8qnf1R7VW0uM+/KzMfHeKXmfIr3xM2DIaH8GTspzoQD/MEklNkxxtMfmTmQmSszc1MdtU00hx5pRkRcCPwixeXjR4F7MtPx1/U6BZgL3A5sjYilwEKKy8YPZuZ9TRanV/x+ub3e90htHgcGgCURMXvoL6cRcTpwKMVwJNVjTrld22LfYNsvR8SszNxWU016tbeV21Ut9t1DcULqlIiYkZm76itL05FBQXOAG4a1rYuISzLzW00U1KHeXG6fBb4HLBq6MyLuAc7PzJ/UXZgKEdELXAjsAab85eJ2kZlbIuLPgL8DVkfEVynmKhwLvAv4JnsDnCbfYFCb22Lf0OFfxwP3T345aqG/3P7f8B2ZuTsi1gELKPprTZ2Fafpx6FFn+wLFuLk5FJNtFgGfB/qAlRGxuLnSOs6R5fbDQC/FxMBDKa4q3AGcDtzWTGkqvQeYBazMzB83XUwnycxrKYa8dAMfBK6gmIz5Y2D58CFJmlRfL7cfjYjXDTZGRDevXgDgF2qtSkMdXm5/NsL+wfZZNdSiac6g0MEy8xOZeWdmPpuZL2XmDzLzwxRn7nqBjzdbYUcZXK4uKK4c/FdmvpiZPwTOo5g0dYZLQTbqQ+X2841W0YEi4nKKYXnLKa4kHAycTDHU5aaI+FRz1XWcmylW/DqW4grPv0TEtRQrhZ1DMVQMwKF5U1eUW1ez0WsyKKiVz5Xb0xutorNsLbdrM/P7Q3dk5g6KqwoAS2qtSgBExJso5pFswCVqaxURZ1JM9P9aZn40M9eWJza+RxGiNwJ/EhGuelSDzNxDMeTrMoplHi8CPkDx3vg1imFhUCydqmYMXjE4fIT9hw07ThqRQUGtDH7AH9xoFZ3lf8vtSJP/BoNEbw21qMpJzM15Z7m9a/iOzHwJeJDiu+ykOovqZJm5OzM/nZknZmZvZh6Wme8AVgMnAjuAHzZbZUcb/D45bviOcojYXGA3rSekS69iUFArg8Nb/BCpzz0UH9y/VK65PNzCcru+tooEvLL2+EUUk5ivb7icTjSj3I60BOpg+0ANtWh0FwEzgVtdzrlRd5bbd7TYdzpwEPAdVzzSWBgUOlRELBg6EW1I+zHAP5ZPvdNpTcolH2+huFR89dB9EfF24DcpLhO3Wu5Ok+sCiomZK5zE3Ih7y+2HIuLooTsi4rco7jK7E/hO3YV1qvKGXsPb3gx8kuJOtX9Re1Ea6naK1aneGxG/MthYnvT4q/LpPzdRmKYf78zcoco7A15BcTl/HcVNi44FllKcEVoBnJeZnqWrSUQcCfw38EaKX44epLjZ1HkUk87el5mufFSziLiXYuz1uzLz35uup9OUNyO8g2IlsBco7gr8DDCfYlhSAB/JzM80VmSHiYgHKIYX/YCiTxZQTGTeRXFX+TtGebn2QXlH7HPLp3MoTh6tZW+Q3pyZlw07/naKEH0zsIVibkl/2f6eMd68TS3sQ39cQbFkMBTD8xZTnNwYnPz/7al6l2aDQoeKiDMoluI8ib3Lo26jWLniBuAGP0TqV17luZIiHBxN8SX8beCvM9M1yWsWEfMpxl1vAPqcn9CMiOgB/hB4L/AmiqETWyjC9Gcz8xsNltdxIuJPKfriWIp5U09ThLlPZub6BktrW+XJvY+NcsiPMrNv2GtOBf6cYjjxTOAJ4F8p3jN+lu2H8fZHRNwNnDHK8V/MzIsnoraJZlCQJEmSVOEcBUmSJEkVBgVJkiRJFQYFSZIkSRUGBUmSJEkVBgVJkiRJFQYFSZIkSRUGBUmSJEkVBgVJkiRJFQYFSZIkSRUGBUmSJEkVBgVJkiRJFQYFSZIkSRUGBUmSJEkVBgVJkiRJFQYFSZIkSRUGBUlS7SJieUTksMfyEY69uMWx6+utWJI6j0FBkiRJUoVBQZIkSVKFQUGSJElShUFBkiRJUoVBQZIkSVJFd9MFSJI0ESLiZODtwBLgLcBRAJkZTdYlSdOVQUGS1C6uApY1XYQktQuDgiRpqjtwjMfdB3wf+J/ysRHomqyiJKndGRQkSVNFzwjtbxjLizPzmqHPIxxxJEn7w8nMkqQmDLRoO3SEYxdNZiGSpNYMCpKkJmxr0bZgeENEzAPeOfnlSJKGMyhIkpqwukXbvIi4avBJRMwFbsV5BpLUiMjMpmuQJHWYiDgKeIrWIWAj8DzQz8gntH6UmX2v8WfsBrpcHlWS9o1XFCRJtcvMp4GbRth9NDCfvd9Ra2opSpL0KgYFSVJTLgW+O8r+AeAK4FP1lCNJGsqgIElqRGZuA04DLqO478ELwE7gCeCfgMXDlzyVJNXHOQqSpLbkHAVJ2j9eUZAkSZJUYVCQJEmSVNHddAGSJE2EiFgKXDWkqatsv39I23WZeV2thUnSNGVQkCS1i9cDb2nRPrRtVU21SNK052RmSZIkSRXOUZAkSZJUYVCQJEmSVGFQkCRJklRhUJAkSZJUYVCQJEmSVGFQkCRJklRhUJAkSZJUYVCQJEmSVGFQkCRJklRhUJAkSZJUYVCQJEmSVGFQkCRJklRhUJAkSZJUYVCQJEmSVGFQkCRJklRhUJAkSZJU8f/iPuPTxUKGxgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 284,
       "width": 389
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "u = eigvects[:, l[:2]]\n",
    "X_proj = X @ u\n",
    "\n",
    "plt.scatter(*X_proj.T, c=y, cmap=\"Set1\")\n",
    "plt.title(\"Principal Subspace\", fontsize=15)\n",
    "plt.xlabel(r\"${\\bf u}_1$\", fontsize=15)\n",
    "plt.ylabel(r\"${\\bf u}_2$\", fontsize=15);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2 style=\"color:crimson\">Minimum Error Formulation</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Applications: PCA as Data Compression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow.keras.datasets import mnist"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = mnist.load_data()\n",
    "train, test = data\n",
    "Xtrain, ytrain = train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_sample = Xtrain[ytrain == 3]\n",
    "N, M, M = X_sample.shape\n",
    "\n",
    "Xbar = X_sample.mean(axis=0)\n",
    "Xhat = (X_sample - Xbar).reshape(N, -1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.93 s, sys: 26.5 ms, total: 1.96 s\n",
      "Wall time: 1.53 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "S = np.einsum(\"ij,ik->jk\", Xhat, Xhat) / N\n",
    "eigvals, eigvects = eig(S)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Because each eigenvector of the covariance matrix is a vector in the original $D$-dimensional space, we can represent the eigenvectors as images of the same size as data points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x288 with 5 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 175,
       "width": 851
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def format_eigval(eigval):\n",
    "    label = rf\"$\\lambda={eigval:.2e}\"\n",
    "    label = label.replace(\"e+0\", \"\\cdot 10^{\")\n",
    "    return label + \"}$\"\n",
    "\n",
    "npc = 4 # number of principal components\n",
    "fig, ax = plt.subplots(1, npc + 1, figsize=(15, 4))\n",
    "\n",
    "\n",
    "principal_subspace = eigvects[:, :npc].reshape(M, M , npc).real\n",
    "eigvectors = [format_eigval(li) for li in eigvals[:npc].real]\n",
    "labels = [\"Mean\"] + eigvectors\n",
    "pca_arrays = np.concatenate((Xbar[..., np.newaxis], principal_subspace), axis=-1)\n",
    "\n",
    "for n, label in enumerate(labels):\n",
    "    ax[n].imshow(pca_arrays[..., n])\n",
    "    ax[n].axis(\"off\")\n",
    "    ax[n].set_title(label)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**The PCA approximation to a data vector ${\\bf x}_n$ is given by**\n",
    "\n",
    "$$\n",
    "    \\tilde{\\bf x}_n = \\bar{\\bf x} + \\sum_{m=1}^M\\left({\\bf x}_n^{\\text T}{\\bf u}_m - \\bar{\\bf x}^{\\text T}{\\bf u}_m\\right) {\\bf u}_m\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f8be33e0850>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 248,
       "width": 251
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(Xhat[[13]].reshape(M, M))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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7Xn+58PL0vmf7e67z74eijuodzfdZz99rG1qTq6vus8Ot/1nW2vtsKwM35auLv+/em48eQJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSAkHgCQEg8ASAkngAQEk8ACIknAITEEwBCpzlJVlWY3qlMirXW2up1/x7a4qG2j7W/LPy6x/5pre+OH2+SbFJYqBqGwkRUa21YHG/n6c26No/1N3c/7j77D28+K909/Zf+SbLFu/elu9urF91HNx/3/9yttba77v+8DbU/UUKePAEgJJ4AEBJPAAiJJwCExBMAQuIJACHxBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSA0GnueRYnEidD/z8w29buXr7ddZ+df3Nfunu+6P91T4baTmGbVO4ubmrOCxuJi9LVbZz2371/qA00fvmbl6XzX939YffZ9ZfPSne/+rL/b7TynrfW2voHH3Sfff9x7QOzvyr87NVHoeNNz54kT54AEBJPAAiJJwCExBMAQuIJACHxBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSA0GlOkh3RWPy6MRYWhyab2h7a5O5d99mL0s2tjdP+iarpvjbNtV8d52xrrQ2L/l/47LH2Ydt9W/vhDw/9919/VfvZp/uh++z779de9/ZZ/+9sd12bQxsLH/WJSbEn5ckTAELiCQAh8QSAkHgCQEg8ASAkngAQEk8ACIknAITEEwBC4gkAIfEEgJB4AkBIPAEgJJ4AEBJPAAid5p5nbTKvjbPCXt9l7e7Nq2X32en2eenu2bcP/YerO6aFncLNbe0Xvn7Vf35/UxtJ3F/371IOF/1nW2ttsq+9b/PH/vND/8e8tdba+4/7P3DVzd3SZ732K6ttctrzfFKePAEgJJ4AEBJPAAiJJwCExBMAQuIJACHxBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQCh05wkKxoKr3r3rDbzdLjo3+ba3N6U7p6vr0rnKza3/d/TKpNirbX2+Mmh//AHu9LdF5f95w/72nfb/a6wA9da27VF99nDsvazz7aFs+va52Wy7z87LU6SmRU7HZ48ASAkngAQEk8ACIknAITEEwBC4gkAIfEEgJB4AkBIPAEgJJ4AEBJPAAiJJwCExBMAQuIJACHxBIDQWe55tsLcX2UL9Lvz/Zfvr2t3j7P+fcehNg3Z9tf9Q4W754U9ztZae96/qbm6KgxLttZms/6Bx7G47Tiuax/WSeH+SfFXNt30/51U9jhba21aOD8p7nlW3nNboE/LkycAhMQTAELiCQAh8QSAkHgCQEg8ASAkngAQEk8ACIknAITEEwBC4gkAIfEEgJB4AkBIPAEgdJ6TZJWpperV1X+gdPnxrp4VJqbaXe073vD+ovvsdr4s3V35wEx2tQ/Lsn+JrbXW2rRw/7R6d2XSrDoLVjhfmhTjpHjyBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSAkHgCQEg8ASAkngAQEk8ACIknAITEEwBC57nnWVHc6zvm3l9lp3C6///7OVKL++ONoI6TYw6w1lQ/a8fcnj3bXcxzfd0nyJMnAITEEwBC4gkAIfEEgJB4AkBIPAEgJJ4AEBJPAAiJJwCExBMAQuIJACHxBICQeAJASDwBIGSS7JyYO4qd7TRWO+/XDv8bT54AEBJPAAiJJwCExBMAQuIJACHxBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSAkHgCQGgyjkb7ACDhyRMAQuIJACHxBICQeAJASDwBICSeABASTwAIiScAhMQTAELiCQAh8QSAkHgCQEg8ASD0P/PbIvvrCMZKAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 231,
       "width": 231
      },
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "xn = Xhat[[13]].T\n",
    "\n",
    "u = eigvects[:, :3].real\n",
    "x_prj = ((xn.T @ u - Xbar.ravel() @ u) * u).sum(axis=1).reshape(M, M)\n",
    "plt.imshow(Xbar + x_prj)\n",
    "plt.axis(\"off\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Animating Projection Error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Jhist = eigvals.real.sum() - eigvals.real.cumsum()\n",
    "Jmax = Jhist.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.animation as animation\n",
    "\n",
    "fig, ax = plt.subplots(1, 2, figsize=(12, 4))\n",
    "\n",
    "nframes = 200\n",
    "def incremental_pca(i):\n",
    "    ax[0].cla()\n",
    "    ax[1].cla()\n",
    "    u = eigvects[:, :i].real\n",
    "    x_prj = ((xn.T @ u - Xbar.ravel() @ u) * u).sum(axis=1).reshape(M, M)\n",
    "    \n",
    "    ax[0].imshow(Xbar + x_prj)\n",
    "    ax[0].set_title(f\"Number of components: {i}\")\n",
    "    ax[0].axis(\"off\")\n",
    "    \n",
    "    ax[1].plot(Jhist[:i])\n",
    "    ax[1].set_ylim(0, Jmax)\n",
    "    ax[1].set_xlim(0, nframes)\n",
    "    ax[1].ticklabel_format(axis=\"y\", useMathText=\"True\",\n",
    "                        scilimits=(0,0))\n",
    "    ax[1].spines[\"top\"].set_visible(False)\n",
    "    ax[1].spines[\"right\"].set_visible(False)\n",
    "    ax[1].set_xlabel(\"Number of Principal Components\", fontsize=12)\n",
    "    ax[1].set_ylabel(r\"$\\bf J$\", fontsize=12)\n",
    "    plt.suptitle(\"PCA Reconstruction\", fontsize=15)\n",
    "    \n",
    "\n",
    "ani = animation.FuncAnimation(fig, incremental_pca, frames=nframes,\n",
    "                              interval=50)\n",
    "# ani.save(\"incremental-pca.gif\", writer=\"imagemagick\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "N, M, M = Xtrain.shape\n",
    "Xbar = Xtrain.mean(axis=0)\n",
    "Xhat = (Xtrain - Xbar).reshape(N, -1)\n",
    "\n",
    "\n",
    "S = np.einsum(\"ij,ik->jk\", Xhat, Xhat) / N\n",
    "eigvals, eigvects = eig(S)\n",
    "\n",
    "u = eigvects[:, :2]\n",
    "proj = Xhat @ u\n",
    "plt.scatter(*proj.T, c=ytrain, alpha=0.8, cmap=\"Dark2\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## PCA for high-dimensional data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_indices = np.random.randint(0, N, 200)\n",
    "X_sample = X_sample[sample_indices]\n",
    "N, M, M = X_sample.shape\n",
    "\n",
    "Xbar = X_sample.mean(axis=0)\n",
    "Xhat = (X_sample - Xbar).reshape(N, -1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "S = np.einsum(\"ij,ik->jk\", Xhat, Xhat) / N\n",
    "eigvals, eigvects = eig(S)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "585"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M ** 2 - N + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "587"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(eigvals.real < 1e-3).sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Further References\n",
    "\n",
    "* http://vlm1.uta.edu/~athitsos/courses/cse4309_spring2020/lectures/12_pca.pdf"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
